#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <mosquitto.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <errno.h>
#include "MQTTClient.h"
#include "cJSON.h"

#define SHM_NAME "/my_shared_memory"           // 共享内存名称
#define SHM_SIZE 2048                          // 共享内存大小（字节）
#define ADDRESS      "mqtt.yyzlab.com.cn"           // MQTT服务器地址           "192.168.3.161" 
#define MQTT_TOPIC "2192568281/Device2AIOTSIM" // MQTT主题         //   "2192568281/APP2AIOTSIM"

// 共享内存中的数据结构示例
typedef struct
{
    float tem;      // 温度
    float hum;      // 湿度
    int light;      // 光照
    bool irrigated; // 喷淋
    bool lamp;      // 灯
    bool warm;      // 加热器
    bool fan;       // 风扇
    bool alarm;     // 报警
    char status[32];
} Project_Data;

int main(int argc, char const *argv[])
{
    int shm_fd;                    // 共享内存文件描述符
    Project_Data *data;            // 共享内存的指针
    struct mosquitto *mqtt_client; // MQTT客户端
    cJSON *root;                   // JSON对象
    char *json_str;                // JSON字符串
    int rc;                        // MQTT连接返回码

    // shmem_to_mqtt(); //创建共享内存
    //  1.打开共享内存对象(只读)
    shm_fd = shm_open(SHM_NAME, O_RDONLY, 0666);
    if (shm_fd == -1)
    {
        perror("shm_open error");
        return -1;
    }

    // 2.将共享内存映射到进程地址空间
    int shmid = shmget(shm_fd, 2048, 0666 | IPC_CREAT);
    if (shmid < 0)
    {
        perror("shmget error");
        close(shm_fd); // 关闭文件描述符
        return -1;
    }
    // 3.初始化MQTT库
    mosquitto_lib_init();                          // 初始化MQTT库(在使用MQTT前)
    mqtt_client = mosquitto_new(NULL, true, NULL); // 创建MQTT客户端
    if (!mqtt_client)                              // 判断MQTT客户端是否创建成功
    {
        perror("mosquitto_new error");
        return -1;
    }

    // 4.连接到MQTT代理
    rc = mosquitto_connect(mqtt_client, ADDRESS, 1883, 60); // 连接MQTT代理
    if (rc != MOSQ_ERR_SUCCESS)                             // 判断连接是否成功
    {
        printf("mosquitto_connect error: %s\n", mosquitto_strerror(rc));
        return -1;
    }
    while (1)
    {
        // 5.创建JSON对象并填充数据
        root = cJSON_CreateObject();                               // 创建JSON对象
        cJSON_AddNumberToObject(root, "tem", data->tem);           // 添加温度字段
        cJSON_AddNumberToObject(root, "hum", data->hum);           // 添加湿度字段
        cJSON_AddNumberToObject(root, "light", data->light);       // 添加光照字段
        cJSON_AddBoolToObject(root, "irrigated", data->irrigated); // 添加喷淋字段
        cJSON_AddBoolToObject(root, "lamp", data->lamp);           // 添加灯字段
        cJSON_AddBoolToObject(root, "warm", data->warm);           // 添加加热器字段
        cJSON_AddBoolToObject(root, "fan", data->fan);             // 添加风扇字段
        cJSON_AddBoolToObject(root, "alarm", data->alarm);         // 添加报警字段
        cJSON_AddStringToObject(root, "status", data->status);     // 添加状态字段

        // 6.发布消息
        json_str = cJSON_Print(root); // 打印JSON字符串
        if (json_str == NULL)
        {
            perror("cJSON_Print error");
            return -1;
        }
        // 发布消息
        rc = mosquitto_publish(mqtt_client, NULL, MQTT_TOPIC, strlen(json_str), json_str, 1, true);
        if (rc != MOSQ_ERR_SUCCESS)
        {
            printf("mosquitto_publish error: %s\n", mosquitto_strerror(rc));
            return -1;
        }
        else
        {
            printf("Published message successful: %s\n", json_str);
        }
    }
    cJSON_Delete(root); // 删除JSON对象
    while (1)
    {
    }

    // 7.清理资源
    free(json_str);                    // 释放JSON字符串内存
    json_str = NULL;                   // 将JSON字符串指针置空
    mosquitto_disconnect(mqtt_client); // 断开MQTT连接
    mosquitto_destroy(mqtt_client);    // 销毁MQTT客户端
    mosquitto_lib_cleanup();           // 清理MQTT库
    shmdt(data);                       // 取消共享内存映射
    shmctl(shmid, IPC_RMID, NULL);
    close(shm_fd); // 关闭共享内存文件描述符

    return 0;
}
